package com.weilus.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Component
public class AuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    TokenService tokenService;
    @Autowired
    SecurityMetadataSourcePropertity propertity;

    private List<RequestMatcher> requestMatchers = Collections.EMPTY_LIST;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        if(requestMatchers.stream().allMatch(m->!m.matches(httpServletRequest))){
            String token = httpServletRequest.getHeader("token");
            if(StringUtils.isEmpty(token)){
                Cookie[] cookies = httpServletRequest.getCookies();
                if(cookies != null) {
                    Optional<Cookie> op = Stream.of(cookies).filter(c -> "token".equals(c.getName())).findFirst();
                    token = op.isPresent() ? op.get().getValue() : null;
                }

            }
            if(!StringUtils.isEmpty(token)) {
                Authentication authentication = tokenService.loadAuthentication(token);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(httpServletRequest,httpServletResponse);
    }

    @Override
    public void afterPropertiesSet() throws ServletException {
        super.afterPropertiesSet();
        if(!CollectionUtils.isEmpty(propertity.getNoCheckToken())) {
            requestMatchers =
                    propertity.getNoCheckToken().stream().map(s -> {
                String httpmethod = null;
                String pattern = s;
                if (s.indexOf(" ") != -1) {
                    String[] arr = StringUtils.delimitedListToStringArray(s, " ");
                    httpmethod = arr[0];
                    pattern = arr[1];
                }
                return new AntPathRequestMatcher(pattern, httpmethod);
            }).collect(Collectors.toList());
        }
    }
}
